/* Verifies that mmap'd regions are only written back on munmap
   if the data was actually modified in memory. */

#include <string.h>
#include <syscall.h>
#include "tests/vm/sample.inc"
#include "tests/lib.h"
#include "tests/main.h"

void
test_main(void) {
    static const char overwrite[] = "Now is the time for all good...";
    static char buffer[sizeof sample - 1];
    char *actual = (char *) 0x54321000;
    int handle;
    mapid_t map;

    /* Open file, map, verify data. */
    CHECK((handle = open("sample.txt")) > 1, "open \"sample.txt\"");
    CHECK((map = mmap(handle, actual)) != MAP_FAILED, "mmap \"sample.txt\"");
    if (memcmp(actual, sample, strlen(sample)))
        fail("read of mmap'd file reported bad data");

    /* Modify file. */
    CHECK(write(handle, overwrite, strlen(overwrite))
          == (int) strlen(overwrite),
          "write \"sample.txt\"");

    /* Close mapping.  Data should not be written back, because we
       didn't modify it via the mapping. */
    msg("munmap \"sample.txt\"");
    munmap(map);

    /* Read file back. */
    msg("seek \"sample.txt\"");
    seek(handle, 0);
    CHECK(read(handle, buffer, sizeof buffer) == sizeof buffer,
          "read \"sample.txt\"");

    /* Verify that file overwrite worked. */
    if (memcmp(buffer, overwrite, strlen(overwrite))
        || memcmp(buffer + strlen(overwrite), sample + strlen(overwrite),
                  strlen(sample) - strlen(overwrite))) {
        if (!memcmp(buffer, sample, strlen(sample)))
            fail("munmap wrote back clean page");
        else
            fail("read surprising data from file");
    } else
        msg("file change was retained after munmap");
}
